<template>
  <div>
    <input type="file" id="file" :multiple="multiple" ref="fileref" name="myfile" accept="image/x-png, image/jpg, image/jpeg, image/gif"
           @change="fileChange($event)" style="display: none"/>

    <!--容器-->
    <div class="cont">
      <!--文件列表-->
      <div class="file-item"  v-for="(item,index) in fileList" :key="index" @click="multiple?showImg(item.url):addFile()">
        <img :src="item.url" style="width: 100%">

        <!--进度条-->
        <div class="progress" v-if="item.progress<100">
          <div :style="{width: item.progress+'%'}" class="progress-i"></div>
        </div>
        <!--上传失败提示-->
        <span style="color: #F56C6C;font-size: 14px;background-color: rgba(0,0,0,0.5)" v-if="item.code==500">上传失败</span>
        <!--删除按钮-->
        <div class="del-item" @click.stop="cancleUploadFile(index)">×</div>
      </div>

      <!--添加文件按钮-->
      <div class="add-file" @click="addFile()" v-if="multiple||fileList.length<1">
        <i style="font-size: 24px;font-family: serif;font-style: normal;cursor: Pointer">＋</i>
        <!--设置按钮-->
        <div class="del-item" @click.stop="springShow=true">⚙</div>
      </div>
    </div>

    <!--图片压缩设置弹窗-->
    <div class="spring-window" v-show="springShowImg" @click="springShowImg=false">
      <div class="spring-cont" >
         <img :src="showImgSrc" style="height: 100%">
      </div>
    </div>

    <!--图片压缩设置弹窗-->
    <div class="spring-window" v-show="springShow" @click="springShow=false">
        <div class="spring-cont" @click.stop="">
          <div class="spring-title">
            图片压缩设置
          </div>
          <div class="spring-info">
            <div>比例：  <input type="text" v-model="cutRatio" /></div>
            <p class="spring-help">比例：图片压缩后的质量(0~1)</p>
            <div>大小：  <input type="text" v-model="cutSize" /></div>
            <p class="spring-help">大小：超过多少KB进行压缩</p>
            <div style="font-size: 12px;color: #606266;display: flex;justify-content: center;align-items: center">
              <input type="checkbox" v-model="springCheck"/>
              记住设置(页面刷新不恢复)
            </div>
          </div>
          <div class="spring-btn">
            <div class="spring-btn-item" style="border-right: 1px solid #e5e5e5;box-sizing: border-box" @click="springShow=false">取消</div>
            <div class="spring-btn-item" style="color: #f90" @click="set()">确定</div>
          </div>
        </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "MyUp",
    props:{
      // 是否支持多选上传
      multiple:{
        type:Boolean,
        default:false,
      },
      // 上传文件类型
      accept:{
        type:String,
        default:'image/*',
      },
    },
    data() {
      return {
        progress: 0,//进度
        medioData:[],
        fileList: [
          // {url:"https://run.51peijia.cn/uploads/20190808/982dea92199a7cd906ea17c0483de742.jpg"}
        ],//文件列表
        cutSize:1024,//超过多少kb压缩，默认1024

        cutRatio:0.7,//超过多少kb压缩，默认1024
        springShow:false,
        springCheck:true,
        showImgSrc:'',
        springShowImg:false,
      }
    },
    watch:{
      medioData(data){
        console.log('editP',this.fileList)
        this.fileList=[]
        data.forEach((value,index)=>{
          console.log('222')
          this.fileList.push({url:value,progress:100,code:200})
        })
      }
    },
    mounted(){
     this.cutSize=this.getCookie("cutSize")||1024
     this.cutRatio=this.getCookie("cutRatio")||0.7
      console.log(this.cutSize,this.cutRatio)
    },
    methods: {
      showImg(data){
        this.showImgSrc=data
        this.springShowImg=true
      },

      //图片压缩比例设置
      set(){
        if(!(this.cutRatio>=0&&this.cutRatio<=1)){
          alert('比例只能在0~1之间')
          return
        }
        if(!(this.cutSize>0)){
          alert('大小必须大于0')
          return
        }
        console.log('设置成功！')
        this.springShow=false
        this.setCookie('cutSize',this.cutSize,30)
        this.setCookie('cutRatio',this.cutRatio,30)
      },
      //添加文件
      addFile(){
        this.$refs.fileref.click()
      },
    //异步文件转base64,返回promise对象
     fileToBase64(file) {
        var ready = new FileReader();
        ready.readAsDataURL(file);
     return new Promise(function (resolve) {
         ready.onload = () => {
           resolve(ready.result);
         }
       })
      },
      //异步获取图片压缩,返回Promise对象
      canvasDataURL(path, obj) {//图片地址，图片比例
        var img = new Image();
        img.src = path;
        return new Promise(function (resolve) {
          img.onload = function () {
            // 默认按比例压缩
            var that = this;
            var w = that.width,
              h = that.height,
              scale = w / h;
            w = obj.width || w;
            h = obj.height || (w / scale);
            var quality = 0.7;  // 默认图片质量为0.7
            //生成canvas
            var canvas = document.createElement('canvas');
            var ctx = canvas.getContext('2d');
            // 创建属性节点
            var anw = document.createAttribute("width");
            anw.nodeValue = w;
            var anh = document.createAttribute("height");
            anh.nodeValue = h;
            canvas.setAttributeNode(anw);
            canvas.setAttributeNode(anh);
            ctx.drawImage(that, 0, 0, w, h);
            // 图像质量
            if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
              quality = obj.quality;
            }
            // quality值越小，所绘制出的图像越模糊
            // 回调函数返回base64的值
            console.log('压缩比例',quality)
            let aaaa=canvas.toDataURL('image/jpeg', quality)
            resolve(aaaa);
            // return canvas.toDataURL('image/jpeg', quality);
          }
        })
      },
     //Base64转Blob
      convertBase64UrlToBlob(urlData) {
        var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], {type: mime});
      },

      fileChange(e){
        var files = this.$refs.fileref.files; // js 获取文件对象
        if(this.multiple){
          let index=this.fileList.length
          console.log(index)
          for(let i of files){
            this.upladFile(i,index)
            index++
          }
        }else {
          this.upladFile(files[0],0)
        }

      },

      //上传文件方法
    async  upladFile(fileObj,index) {
      if(!fileObj){
        console.log('未选取任何文件')
        return
      }
       let re=await this.fileToBase64(fileObj);
      var url = "https://api.zjzcpt.com/index/Tool/upload"; // 接收上传文件的后台地址
        var form = new FormData(); // FormData 对象
      if (fileObj.size / 1024 > this.cutSize) { //大于1M，进行压缩上传
         this.fileListAdd(re,index)
          let base64Codes=await this.canvasDataURL(re, {quality: this.cutRatio})
          var bl = this.convertBase64UrlToBlob(base64Codes);
          form.append("file", bl, "file_" + Date.parse(new Date()) + ".jpg"); // 文件对象
          this.ajax({url,data:form,suc:this.ajaxSuccess,err:this.ajaxErr,change:this.progressFunction,index})
        }else {
          this.fileListAdd(re,index)
        form.append("file", fileObj); // 文件对象

        this.ajax({url,data:form,suc:this.ajaxSuccess,err:this.ajaxErr,change:this.progressFunction,index})
        }
      },
      //ajax请求
      ajax({url,data,suc,err,change,index}){//地址，请求参数，成功执行的回调，失败执行的回调,上传进度调用的方法
          let xhr = this.xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
          xhr.open("post", url, true); //post方式，url为服务器请求地址，true 该参数规定请求是否异步处理。
          xhr.onreadystatechange = () =>{
            if (xhr.readyState == 4){
              if(xhr.status==200){
                suc(xhr) //请求成功
              }else {
                err(index)||console.log('请求失败')
              }
            }
          };
        if (change){
          // xhr.upload.onprogress=this.progressFunction//上传进度调用的方法
          // xhr.upload.onprogress=change//上传进度调用的方法
         change(xhr,index)
          // xhr.upload.onprogress=function (event,innn) {
          //   console.log(event,innn)
          // }//上传进度调用的方法
        }
          // xhr.upload.onprogress = this.progressFunction(event);//【上传进度调用方法实现】

          // xhr.upload.onloadstart = function () {//上传开始执行方法
          //   ot = new Date().getTime();   //设置上传开始时间
          //   oloaded = 0;//设置上传开始时，以上传的文件大小为0
          // };
          xhr.send(data); //开始上传，发送form数据
      },
      //请求成功
      ajaxSuccess(value){
        console.log('请求成功')
        console.log(value)
        let data=JSON.parse(value.response)
        console.log(data)
        this.postChange(data)
      },
      //提交change
      postChange(data){
        this.$emit('change',data.data.url);
      },
      //请求失败
      ajaxErr(index){
        this.fileList[index].code=500
      },
      //取消上传
      cancleUploadFile(index) {
        if(this.xhr)
        this.xhr.abort();
        this.fileListDel(index)
      },
      //文件列表增加
      fileListAdd(file){
        if(this.multiple){//是否支持多张上传
          this.fileList.push({url:file,progress:0,code:200})

        }else {
          this.fileList=[{url:file,progress:0,code:200}]

        }
        console.log(this.fileList)
      },
      //文件列表删除
      fileListDel(index){
       this.fileList.splice(index,1)
        this.$emit('changedel',index);
      },

      //上传进度实现方法，上传过程中会频繁调用该方法
      progressFunction(evt,index) {
        console.log(index)
        evt.upload.onprogress=(e)=>{
          this.fileList[index].progress=Math.round(e.loaded / e.total * 100)
       }
        // event.total是需要传输的总字节，event.loaded是已经传输的字节。如果event.lengthComputable不为真，则event.total等于0
        // if (evt.lengthComputable) {//
        //   this.progress = Math.round(evt.loaded / evt.total * 100)
        //   console.log(this.progress)
        // }

        // var time = document.getElementById("time");
        // var nt = new Date().getTime();//获取当前时间
        // var pertime = (nt - ot) / 1000; //计算出上次调用该方法时到现在的时间差，单位为s
        // ot = new Date().getTime(); //重新赋值时间，用于下次计算
        // var perload = evt.loaded - oloaded; //计算该分段上传的文件大小，单位b
        // oloaded = evt.loaded;//重新赋值已上传文件大小，用以下次计算
        // //上传速度计算
        // var speed = perload / pertime;//单位b/s
        // var bspeed = speed;
        // var units = 'b/s';//单位名称
        // if (speed / 1024 > 1) {
        //   speed = speed / 1024;
        //   units = 'k/s';
        // }
        // if (speed / 1024 > 1) {
        //   speed = speed / 1024;
        //   units = 'M/s';
        // }
        // speed = speed.toFixed(1);
        // //剩余时间
        // var resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1);
        // time.innerHTML = '，速度：' + speed + units + '，剩余时间：' + resttime + 's';
        // if (bspeed == 0) time.innerHTML = '上传已取消';
      },
      //获取cookie
      getCookie(name) {
        name = name + "="
        var start = document.cookie.indexOf(name),
          value = null;
        if (start > -1) {
          var end = document.cookie.indexOf(";", start);
          if (end == -1) {
            end = document.cookie.length;
          }
          value = document.cookie.substring(start + name.length, end);
        }
        return value;
      },
      //设置cookie
      setCookie(cname, cvalue, exdays) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires=" + d.toUTCString();
        console.info(cname + "=" + '111' + "; " + expires);
        document.cookie = cname + "=" + cvalue + "; " + expires;
      },
    }
  }
</script>

<style scoped>
  .cont {
    display: flex;
    margin: 10px;
    flex-wrap:wrap;
  }

  .progress {
    width: 80%;
    background-color: #ebeef5;
    border-radius: 99px;
  }

  .progress-i {
    height: 5px;
    background-color: #67C23A;
    position: relative;
    border-radius: 99px;
  }

  .file-item {
    width: 100px;
    height: 100px;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
    border-radius: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    margin-right: 10px;
    margin-bottom: 10px;
    border: 1px solid #f5f5f5;
    box-sizing: border-box;
  }

  .del-item {
    position: absolute;
    top: -3px;
    right: -5px;
    width: 15px;
    line-height: 15px;
    text-align: center;
    color:#FFF ;
    background-color: #F56C6C;
    border-radius: 99px;
    cursor:pointer;
  }
  .del-item:hover{
    background-color: #f59386
  }

  .add-file{
    width: 100px;
    height: 100px;
    line-height: 100px;
    border: 1px dashed #c0ccda ;
    border-radius: 6px;
    text-align: center;
    color: #8c939d;
    cursor: Pointer;
    position: relative;
  }
  .add-file:hover{
    border-color: #409EFF;
  }
  .spring-window{
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.3);
    z-index: 999;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: auto;
  }
  .spring-cont{
    background-color: #fff;
    border-radius: 5px;
    min-width: 300px;
  }
  .spring-title{
    font-size: 18px;
    color: #303133;
    text-align: center;
    padding-top: 10px;
    box-sizing: border-box;
  }
  .spring-info{
    padding: 20px;
    box-sizing: border-box;
    font-size: 14px;
    color: #303133;
    text-align: center;
  }
  .spring-btn{
    width: 100%;
    border-top: 1px solid #e5e5e5;
    display: flex;
    justify-content: space-between;
    font-size: 18px;
  }
  .spring-btn-item{
    width: 100%;line-height: 40px;cursor:pointer;text-align: center;
  }
  .spring-btn-item:active{
   background-color: #e5e5e5;
  }
  .spring-help{
    padding: 0;
    margin: 0;
    font-size: 12px;
    color: #909399;
  }
</style>
